/*
*******************************************************************************
** Copyright (C), 2014-2020, TONLY AV R&D CENTER SOFTWARE DEVELOPMENT DEPARTMENT
** FileName: 
** <author>:             
** Date:
** Description:
**
** Others:
** Function List:
**   1.
** History:
**  <Author>    <date>    <content>    <version>
*******************************************************************************
*/
//*****************************************************************************
// File Include
//*****************************************************************************
#include "input_mesh.h"
#include "app_log.h"
#include "input_ring_buffer.h"
#include <string.h>
#include "cdn_light.h"
#include "cdn_pwm.h"
#include "sl_bt_api.h"

//*****************************************************************************
// API Functions
//*****************************************************************************
void mesh_vendor_rsp(uint16_t source_address, uint8_t *payload)
{
	uint8_t ReciveCmd = 0;
	ReciveCmd = *payload;
	
  sl_status_t send_rsp = sl_btmesh_vendor_model_send(source_address,0,0,0,0x0211,0,0,CDN_VENDOR_OP_ACK,1,1,&ReciveCmd);
  if(send_rsp == SL_STATUS_OK)
  {
    TRACE("mesh_vendor_rsp RSP Success,ReciveCmd = 0x%x !\r\n",ReciveCmd);
		cdn_get_node_primary_element_seqnum();
  }
  else
  {
    TRACE("mesh_vendor_rsp RSP Fail SC = 0x%lx \r\n",send_rsp);
  }
}

void mesh_vendor_data_get(sl_btmesh_msg_t *evt)
{
  InputEvent event = {0};
  uint8_t rec_len = evt->data.evt_vendor_model_receive.payload.len;
  if(rec_len >= MESH_BUF_LEN)
  {
    return;
  }
  memcpy(&event.imesh[4],evt->data.evt_vendor_model_receive.payload.data,rec_len);  //真实数据从第4位开始存

  event.eType = INPUT_EVENT_TYPE_MESH;
  event.imesh[0] = (evt->data.evt_vendor_model_receive.source_address) >> 8;        //源地址高字节
  event.imesh[1] = (evt->data.evt_vendor_model_receive.source_address) & 0xff;      //源地址低字节
  event.imesh[2] = (evt->data.evt_vendor_model_receive.destination_address) >> 8;   //目的地址高字节
  event.imesh[3] = (evt->data.evt_vendor_model_receive.destination_address) & 0xff; //目的地址低字节

  //TRACE("zsm Mesh RX RX RX RX: mesh_vendor_data_get source_address = 0x%x%x\r\n",event.imesh[0],event.imesh[1]);
  //TRACE("zsm Mesh RX RX RX RX: mesh_vendor_data_get destination_address = 0x%x%x\r\n",event.imesh[2],event.imesh[3]);

  if(PutOtherInputEvent(&event))
  {
    TRACE("zsm Mesh RX RX RX RX: mesh_vendor_data_get PutOtherInputEvent ERROR\r\n");
  }

  TRACE("zsm Mesh RX evt_vendor_model_receive.opcode = 0x%x\r\n",(evt->data.evt_vendor_model_receive.opcode + 0xc0));
  if(CDN_VENDOR_OP_NOACK != evt->data.evt_vendor_model_receive.opcode &&
     0xffff != evt->data.evt_vendor_model_receive.destination_address)
  {
    //mesh_vendor_rsp(evt->data.evt_vendor_model_receive.source_address, evt->data.evt_vendor_model_receive.payload.data);
		//回复APP发过来的包，回复内容是APP的发包内容
		sl_btmesh_vendor_model_send(evt->data.evt_vendor_model_receive.source_address, // 目标地址
																												        0, // va_index
																												        0, // appkey_index
																												        0, // elem_index
																												        0x0211, // vendor_id
																												        0, // model_id
																												        0, // nonrelayed
																												        CDN_VENDOR_OP_ACK, // 操作码
																												        1, // final
																												        evt->data.evt_vendor_model_receive.payload.len, // payload_len
																												        evt->data.evt_vendor_model_receive.payload.data // payload
																												    		);

	}
}

void MeshEventInputHandler(PInputEvent MeshEvent)
{
  uint16_t adr_src = (MeshEvent->imesh[0]) << 8 | MeshEvent->imesh[1];
  uint16_t adr_dst = (MeshEvent->imesh[2]) << 8 | MeshEvent->imesh[3];
  uint8_t *par = &(MeshEvent->imesh[4]);

  TRACE("zx: MeshEventInputHandler adr_src:0x%04x,adr_dst:0x%04x\n",adr_src,adr_dst);
  TRACE("zx: MeshEventInputHandler [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]\n",par[0],par[1],par[2],par[3],par[4],par[5],par[6],par[7],par[8],par[9]);

  switch(par[0])
  {
    case APP_TX_INQUIRE_GROUP_LEADER: //APP查询组参数
      {
				uint16_t GroupAdr = (par[2]<<8) | par[1];
        CheckGroupLeaderAck(GroupAdr,adr_src);
      }
      break;
		case APP_TX_SET_DRIVER_POWER: //灯驱动器功率范围设置
		  {
        uint16_t GroupAdr = (0xC0<<8) | par[1];
        uint8_t PowerMode = par[2];
		    SetCurrentGroupLightnessPowerValue(GroupAdr,PowerMode);
		  }
		  break;
    case APP_TX_LIGHT_TO_GROUP: //APP发命令设置灯分组
      {
				TRACE("zx: APP_TX_LIGHT_TO_GROUP element_address:0x%04x\n",cdn_get_element_address());
        if(adr_dst == cdn_get_element_address())
        {
          uint16_t GroupAdr = (par[2]<<8) | par[1];
          uint8_t GroupLeader = par[3];
					uint8_t RoomArea = par[4];
          LedGroupBind(GroupAdr,GroupLeader,RoomArea);
        }
      }
      break;
    case APP_TX_VERIFY_GROUP_LEADER: //APP删除灯前查询该灯是否是组长
      {
        if(adr_dst == cdn_get_element_address())
        {
          LedInfoAck(adr_src);
        }
      }
      break;		
		case VOICE_TX_SET_GROUP_FUNCTION:	 //语音设置 组 亮度/色温百分比
    case APP_TX_SET_GROUP_FUNCTION:    //APP设置某组的亮度和色温
      {			
        uint16_t GroupAdr = (par[2]<<8) | par[1];
				uint8_t SecondCmd = par[3];
        uint8_t Lightness = GetCurrentBrightness();
        uint8_t CT = GetCurrentCTvalue();

        LedCurrentGroupOffJudge(GroupAdr);

				if(0x01 == SecondCmd)
				{
					Lightness = par[4];
        	CT = par[5];
				}
				else if(0x02 == SecondCmd)
				{
					Lightness = par[4];
				}
				else if(0x03 == SecondCmd)
				{
					CT = par[4];
					VoiceSetRoomLightnessCtAdj(par[5],GetCurrentBrightness(),CT);	//带屏面板调节整个房间色温
				}
				TRACE("zx: APP_TX_SET_GROUP_FUNCTION SecondCmd = %d,Lightness = %d,CT = %d\n",SecondCmd,Lightness,CT);

				//防御性编程
        if(Lightness > PWM_MAX_DUTY_CYCLE)
        {
          Lightness = PWM_MAX_DUTY_CYCLE;
        }
        if(CT > PWM_MAX_DUTY_CYCLE)
        {
          CT = PWM_MAX_DUTY_CYCLE;
        }
        SetCurrentGroupLightnessCT(GroupAdr,Lightness,CT);
      }
      break;
		case VOICE_TX_ADJ:		//语音调节某个组亮/暗/白/暖 一点
			{
				uint16_t GroupAdr = (par[2]<<8) | par[1];
				uint8_t SecondCmd = par[3];
        uint8_t volatile Lightness = GetCurrentBrightness();
        uint8_t volatile CT = GetCurrentCTvalue();
				LedCurrentGroupOffJudge(GroupAdr);

				if(Lightness == 0)
					Lightness = 5;
				
				if(0x01 == SecondCmd)				//亮一点
				{
					Lightness += 25;
				}
				else if(0x02 == SecondCmd)	//暗一点
				{
					if(Lightness > 25)
						Lightness -= 25;
					else
						Lightness = 1;
				}
				else if(0x03 == SecondCmd)	//白一点
				{
					CT += 30;
				}
				else if(0x04 == SecondCmd)	//暖一点
				{
					if(CT > 30)
						CT -= 30;
					else
						CT = 0;
				}
				TRACE("zx: VOICE_TX_ADJ SecondCmd = %d,Lightness = %d,CT = %d\n",SecondCmd,Lightness,CT);

				//防御性编程
        if(Lightness > PWM_MAX_DUTY_CYCLE)
        {
          Lightness = PWM_MAX_DUTY_CYCLE;
        }
				
        if(CT > PWM_MAX_DUTY_CYCLE)
        {
          CT = PWM_MAX_DUTY_CYCLE;
        }
        VoiceSetGroupLightnessCtAdj(GroupAdr,Lightness,CT);
			}
		break;
		case VOICE_TX_ROOM_ADJ:		//语音控制整个房间亮/暗/白/暖一点
			{
				uint16_t RoomId = par[1];
				uint8_t SecondCmd = par[2];
        uint8_t volatile Lightness = GetCurrentBrightness();
        uint8_t volatile CT = GetCurrentCTvalue();

				if(Lightness == 0)
					Lightness = 5;
				
				if(0x01 == SecondCmd)				//亮一点
				{
					Lightness += 25;
				}
				else if(0x02 == SecondCmd)	//暗一点
				{
					if(Lightness > 25)
						Lightness -= 25;
					else
						Lightness = 1;
				}
				else if(0x03 == SecondCmd)	//白一点
				{
					CT += 30;
				}
				else if(0x04 == SecondCmd)	//暖一点
				{
					if(CT > 30)
						CT -= 30;
					else
						CT = 0;
				}
				TRACE("zx: VOICE_TX_ROOM_ADJ RoomId = %d,Lightness = %d,CT = %d\n",RoomId,Lightness,CT);

				//防御性编程
        if(Lightness > PWM_MAX_DUTY_CYCLE)
        {
          Lightness = PWM_MAX_DUTY_CYCLE;
        }
				
        if(CT > PWM_MAX_DUTY_CYCLE)
        {
          CT = PWM_MAX_DUTY_CYCLE;
        }				
				VoiceSetRoomLightnessCtAdj(RoomId,Lightness,CT);
			}
			break;
		case VOICE_TX_ROOM_DEV_ONOFF:	 //语音控制某房间设备全开或者全关
			{
				if(par[1] == 0xff)	//没有指定房间就是全屋灯
				{
					VoiceCtrlAllBulbOnOff(par[2]);
				}
				else
				{
					LedCurrentRoomOnOffCtrl(par[1],par[2]);
				}
			}
			break;
		case VOICE_TX_SET_ROOM_FUNCTION:	 //语音设置 房间 亮度/色温百分比
			{
        uint16_t RoomId = par[1];
				uint8_t SecondCmd = par[2];
        uint8_t volatile Lightness = GetCurrentBrightness();
        uint8_t volatile CT = GetCurrentCTvalue();

				if(0x02 == SecondCmd)
				{
					Lightness = par[3];
				}
				else if(0x03 == SecondCmd)
				{
					CT = par[3];
				}
				TRACE("zx: VOICE_TX_SET_ROOM_FUNCTION SecondCmd = %d,Lightness = %d,CT = %d\n",SecondCmd,Lightness,CT);

				//防御性编程
        if(Lightness > PWM_MAX_DUTY_CYCLE)
        {
          Lightness = PWM_MAX_DUTY_CYCLE;
        }
        if(CT > PWM_MAX_DUTY_CYCLE)
        {
          CT = PWM_MAX_DUTY_CYCLE;
        }
        VoiceSetRoomLightnessCtAdj(RoomId,Lightness,CT);
			}
			break;
		case VOICE_TX_CTRL_ALL_GROUP:	 		//语音控制所有灯开闭
			{
				VoiceCtrlAllBulbOnOff(par[1]);
			}
			break;
    case KEY_TX_LIGHT_ONOFF:  			//收到本地回路按键按下后发出的组号
    case APP_TX_GROUP_ALL_ONOFF:		//APP控制某组设备全开或者全关
		case VOICE_TX_GROUP_ALL_ONOFF:	//语音控制某组设备全开或者全关
      {
        uint16_t GroupAdr = (par[2]<<8) | par[1];

        LedCurrentGroupOnJudge(GroupAdr);
        LedCurrentGroupOnOffCtrl(GroupAdr,par[3]);
      }
      break;
    case APP_TX_SET_SCENE_LIGHTNESS_CT: //APP发命令设置场景下有关组的亮度和色温
      {
        uint8_t SceneId = par[1];
        uint16_t GroupAdr = (par[3]<<8) | par[2];
				uint8_t SecondCmd = par[4];
	      uint8_t Lightness = 0;
        uint8_t CT = 0;

        LedCurrentGroupOnJudge(GroupAdr);

				switch(SecondCmd)
				{
					case 0x01:
					{
						Lightness = par[5];
        		CT = par[6];
						SetSceneGroupLightnessCT(SceneId,GroupAdr,Lightness,CT);
					}
					break;

					case 0x02:
					{
						Lightness = par[5];
						CT = PWM_MIN_DUTY_CYCLE;
						SetSceneGroupLightnessCT(SceneId,GroupAdr,Lightness,CT);
					}
					break;

					case 0x03:
					{
						Lightness = par[5];
	        	CT = par[6];
						ConfirmSceneGroupLightnessCT(SceneId,GroupAdr,Lightness,CT);
					}
					break;

					case 0x04:
					{
						DeleteCurrentGroupSceneId(SceneId, GroupAdr);
					}
					break;

					default:
						break;
				}
      }
      break;
    case APP_TX_RECALL_SCENE:
    case BODY_TX_RECALL_SCENE:
    case KEY_TX_RECALL_SCENE: //收到场景按键按下后发出的场景ID
      {
        uint8_t SceneId = par[1];
        uint8_t SceneOnoff = par[2];
        SceneRecall(SceneId,SceneOnoff);
      }
      break;
    case KEY_TX_DIMMING:  //长按调光指令
      {
        uint16_t GroupAdr = (par[3]<<8) | par[2];
        uint8_t DimmingCmd = par[1];

        LedCurrentGroupOffJudge(GroupAdr);

        LightnessDimmingCtrlByKey(GroupAdr, DimmingCmd);
      }
      break;
    case KEY_TX_ADJUST_CCT: //长按调色指令
      {
        uint8_t CCT_Cmd = par[1];
				uint8_t CCT_RoomArea = par[2];
				uint16_t CCT_GroupAddr = (uint16_t)((0xC0 << 8) | par[4]);

				LightnessCCTCtrlByKey(CCT_GroupAddr,CCT_Cmd,CCT_RoomArea);
      }
      break;
    case LIGHT_TX_GROUP_LIGHTNESS_CT:  //组长返回亮度和色温
      {
        uint16_t GroupAdr = (par[2]<<8) | par[1];
        GroupLightnessCCTSync(GroupAdr,par[3],par[4]);//同步亮度和色温信息
      }
      break;
		case KEY_TX_CCT_ONOFF: //短按调色指令
			{
				uint8_t CCT_OnOff_Cmd = par[1];
				uint8_t CCT_RoomArea = par[2];
				uint16_t CCT_GroupAddr = (uint16_t)((0xC0 << 8) | par[4]);
				
				LightCTChangeByKeyClick(CCT_GroupAddr, CCT_OnOff_Cmd,CCT_RoomArea);
			}
			break;
    case APP_TX_FACTORY_RESET:  //恢复出厂设置
      {
        if(adr_dst == cdn_get_element_address())
        {
          sl_btmesh_initiate_node_reset();  //清除信息并重启
          TRACE("zsm: APP_TX_FACTORY_RESET \r\n");
        }
      }
      break;
		case APP_TX_DELETE_SCENE:		//删除场景
			{
				uint8_t SceneID = par[1];
				uint8_t Detele = par[2];
				
				if(Detele)
				{
					DeleteCurrentSceneid(SceneID);
				}
			}
			break;
    case APP_TX_DELETE_GROUP:   //删除组
      {
				uint16_t GroupAdr = (par[2]<<8) | par[1];
				uint8_t Reset = par[3];
				DeleteGroup(GroupAdr,Reset);
      }
      break;
    case APP_TX_LIGHT_CTRL:  //单灯控制亮灭
      {
        if(adr_dst == cdn_get_element_address())
        {
          SetGroupOnoffJudgeFlag(1);
					if(par[1])
					{
						if(GetPreTargetBrightness() == 0)
						{
							SetLightnessCTFadesCtrl(100, GetCurrentCTvalue());
						}
						else
						{
							SetLightnessCTFadesCtrl(GetPreTargetBrightness(), GetCurrentCTvalue());
						}
					}
					else
					{
						SetLightnessCTFadesCtrl(0, GetCurrentCTvalue());
					}
          TRACE("zsm: APP_TX_LIGHT_CTRL \r\n");
        }
        else
        {
          TRACE("zx: adr_det different\n");
        }
      }
      break;
		case APP_TX_BROADCAST:
			{
				uint8_t SecondCmd = par[1];
				TRACE("zx: APP_TX_BROADCAST SecondCmd = 0x%02x,data = %d\n",SecondCmd,par[2]);
				if(0xFF == SecondCmd)
				{
					uint8_t data = par[2];
					if(data)
					{
						TRACE("lj: APP_TX_BROADCAST Delete whole network !\n");
						sl_btmesh_initiate_node_reset();    //清除信息并重启
					}
				}
			}
		break;
    default:
      break;
  }
}


